using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent), typeof(CharacterStats), typeof(BoxCollider))]
public class EnemyController : MonoBehaviour, IEndGameObserver
{
    private NavMeshAgent agent;
    private Animator anim;
    /// <summary>
    /// 敌人属性
    /// </summary>
    protected CharacterStats enemyStat;
    /// <summary>
    /// 敌人的四种状态
    /// </summary>
    private EnemyStates enemyStates;
    // 玩家
    protected GameObject attackTarget;

    // 动画
    private bool isWalk;
    private bool isChase;
    private bool isFollow;
    private bool isDead;


    [Header("base setttings")]
    // 视野范围
    public float sightRadius;
    /// <summary>
    /// 是否属于站桩守卫类敌人
    /// </summary>
    public bool isGuard;
    // TODO: 在血条左边显示蓝白小圆环，表示攻击冷却
    // 与上一次攻击所间隔的时间
    private float lastAttackTime;

    /// <summary>
    /// 记录初始出生点
    /// </summary>
    private Vector3 guardPos;
    /// <summary>
    /// 记录初始移动速度：方便在返回时减速返回，追击玩家时使用正常速度
    /// </summary>
    private float moveSpeed;
    /// <summary>
    /// 巡逻类敌怪的走动范围
    /// </summary>
    [Header("Patrol setttings")]
    public float patrolRange;
    // 巡逻的位置点
    private Vector3 wayPoint;
    /// <summary>
    /// 巡逻一个点后，需要等待的时间，再巡逻另一个点
    /// </summary>
    [Range(1, 3)]
    public float lookAtTime;
    /// <summary>
    /// 到达巡逻点后，已经等待的时间的计数器
    /// </summary>
    private float remainLookAtTime;

    public enum EnemyStates
    {
        GUARD, PATROL, CHASE, DEAD
    }
    // 原本的旋转角度
    private Quaternion guardQuaternion;
    // 碰撞体
    private Collider coll;
    // 玩家已死亡
    private bool playerDead;

    void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>();
        enemyStat = GetComponent<CharacterStats>();
        coll = GetComponent<Collider>();

    }
    private void OnEnable()
    {
        GameManager.Instance.AddEndGameObservers(this);
    }
    private void OnDisable()
    {
        if (!GameManager.IsInitialized)
        {
            return;
        }
        GameManager.Instance.RemoveEndGameObservers(this);
        // 掉落物品
        if (GetComponent<LootSpawner>() && isDead)
        {
            GetComponent<LootSpawner>().SpawnLoot();
        }
        // 检测任务需求,更新任务进度
        if (QuestManager.IsInitialized && isDead)
        {
            QuestManager.Instance.UpdateQuestProcess(this.name, 1);
        }
    }
    void Start()
    {
        moveSpeed = agent.speed;
        guardPos = transform.position;
        GetNewWayPoint();
        enemyStates = isGuard ? EnemyStates.GUARD : EnemyStates.PATROL;
        guardQuaternion = transform.rotation;
        remainLookAtTime = lookAtTime;
    }
    void Update()
    {
        if (enemyStat.CurrentHealth <= 0)
        {
            isDead = true;
        }
        if (!playerDead)
        {
            if (lastAttackTime > 0)
            {
                lastAttackTime -= Time.deltaTime;
            }
            SwitchStates();
            SwitchAnimation();
        }
    }

    private void SwitchAnimation()
    {
        anim.SetBool("Walk", isWalk);
        anim.SetBool("Follow", isFollow);
        anim.SetBool("Chase", isChase);
        anim.SetBool("Death", isDead);
    }
    /// <summary>
    /// 敌人状态机
    /// </summary>
    private void SwitchStates()
    {
        if (isDead)
        {
            enemyStates = EnemyStates.DEAD;
        }
        else if (FindPlayer() && enemyStates != EnemyStates.CHASE)
        {
            // 从其他状态切换为追逐状态
            enemyStates = EnemyStates.CHASE;
            remainLookAtTime = 0;
        }
        switch (enemyStates)
        {
            case EnemyStates.GUARD:
                isChase = false;
                agent.speed = moveSpeed * 0.5f;
                // 不再原位时移到到原位
                if (transform.position != guardPos)
                {
                    isWalk = true;
                    agent.isStopped = false;
                    agent.destination = guardPos;
                    // 回到原位并停下
                    if (Vector3.SqrMagnitude(guardPos - transform.position) <= agent.stoppingDistance)
                    {
                        isWalk = false;
                        transform.rotation = Quaternion.Lerp(transform.rotation, guardQuaternion, 0.01f);
                    }
                }
                break;
            case EnemyStates.PATROL:
                isChase = false;
                agent.speed = moveSpeed * 0.5f;
                // 没有移动到巡逻点，开始移动
                if (Vector3.Distance(transform.position, wayPoint) > agent.stoppingDistance)
                {
                    isWalk = true;
                    agent.destination = wayPoint;
                }
                // 移动到了巡逻点
                else
                {
                    isWalk = false;
                    if (remainLookAtTime > 0)
                    {
                        remainLookAtTime -= Time.deltaTime;
                    }
                    GetNewWayPoint();
                }
                break;
            case EnemyStates.CHASE:
                isWalk = false;
                isChase = true;
                agent.speed = moveSpeed;
                // 攻击目标丢失
                if (!FindPlayer())
                {
                    isFollow = false;
                    if (remainLookAtTime > 0)
                    {
                        agent.destination = transform.position;
                        remainLookAtTime -= Time.deltaTime;
                    }
                    else
                    {
                        enemyStates = isGuard ? EnemyStates.GUARD : EnemyStates.PATROL;
                    }
                }
                // 攻击目标存在
                else
                {
                    isFollow = true;
                    agent.isStopped = false;
                    agent.destination = attackTarget.transform.position;
                }
                if (TargetInAttackRange() || TargetInSkillRange())
                {
                    isFollow = false;
                    agent.isStopped = true;

                    if (lastAttackTime <= 0)
                    {
                        lastAttackTime = enemyStat.attackData.coldDown;
                        // 暴击判断
                        enemyStat.isCritical = UnityEngine.Random.value <= enemyStat.attackData.criticalRate;
                        Attack();
                    }
                }

                break;
            case EnemyStates.DEAD:
                coll.enabled = false;
                // 不禁用是因为敌人死亡时，动画脚本中的 update 仍然在执行。
                agent.radius = 0;
                // 2 秒后删除
                Destroy(gameObject, 2f);
                break;
        }
    }
    bool TargetInAttackRange()
    {
        if (attackTarget != null)
        {
            return Vector3.Distance(attackTarget.transform.position, transform.position) <= enemyStat.attackData.attackRange;
        }
        return false;
    }
    bool TargetInSkillRange()
    {
        if (attackTarget != null)
        {
            return Vector3.Distance(attackTarget.transform.position, transform.position) <= enemyStat.attackData.skillRange;
        }
        return false;
    }
    /// <summary>
    /// 普通攻击
    /// </summary>
    public void Attack()
    {
        transform.LookAt(attackTarget.transform.position);
        if (TargetInSkillRange())
        {
            enemyStat.isCritical = UnityEngine.Random.value <= enemyStat.attackData.criticalRate;
            anim.SetBool("Critical", enemyStat.isCritical);
            anim.SetTrigger("Skill");
        }
        else if (TargetInAttackRange())
        {
            enemyStat.isCritical = UnityEngine.Random.value <= enemyStat.attackData.criticalRate;
            anim.SetBool("Critical", enemyStat.isCritical);
            anim.SetTrigger("Attack");
        }
    }
    private bool FindPlayer()
    {
        Collider[] colliders = Physics.OverlapSphere(transform.position, sightRadius);
        foreach (var target in colliders)
        {
            if (target.CompareTag("Player"))
            {
                attackTarget = target.gameObject;
                return true;
            }
        }
        attackTarget = null;
        return false;
    }
    private void GetNewWayPoint()
    {
        // 重置到达巡逻点后的等待时间
        remainLookAtTime = lookAtTime;

        // 巡逻怪的逻辑 -- 从出生点的巡逻半径范围内选择一个点进行移动
        // 获取可移动的点
        float x = UnityEngine.Random.Range(-patrolRange, patrolRange);
        float z = UnityEngine.Random.Range(-patrolRange, patrolRange);
        // 此处 Y 轴使用自身的 Y 轴位置
        Vector3 randomPos = (new Vector3(guardPos.x + x, transform.position.y, guardPos.z + z));

        NavMeshHit hit;
        // 从patrolRange的搜索半径范围内对ret点进行采样，判断玩家能否移动到该点附近
        // 最后一个参数 1 是 navmesh area 编号的值
        if (NavMesh.SamplePosition(randomPos, out hit, patrolRange, 1))
        {
            wayPoint = hit.position;
        }
        else
        {
            wayPoint = transform.position;
        }
    }
    private void OnDrawGizmosSelected()
    {
        // 绘制巡逻范围
        Gizmos.color = Color.blue;
        Gizmos.DrawWireSphere(transform.position, patrolRange);
        Gizmos.color = Color.red;
        Gizmos.DrawLine(transform.position, wayPoint);
        if (agent != null)
        {
            Gizmos.color = Color.yellow;
            Gizmos.DrawLine(transform.position, agent.destination);
        }

    }
    // Animation Event
    void Hit()
    {
        if (attackTarget != null && transform.IsFacingTarget(attackTarget.transform))
        {
            var targetStat = attackTarget.GetComponent<CharacterStats>();

            targetStat.TakeDamage(enemyStat, targetStat);
        }

    }

    public void EndNotify()
    {
        isChase = false;
        isWalk = false;
        playerDead = true;
        // 停止移动
        // 停止 agent
        attackTarget = null;
        // 获胜动画
        anim.SetBool("Win", true);
    }
}
